package com.pvdnc.nsocket;

import com.pvdnc.nsocket.log.SLog;
import com.pvdnc.nsocket.protocol.base.Packet;

import java.util.HashMap;
import java.util.Map;

import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;

public class ManagedChannel {
    private static final SLog LOG=new SLog(ManagedChannel.class);

    private static final Map<Channel,ManagedChannel> mInstanceMap=new HashMap<>();

    public static ManagedChannel getInstance(Channel channel){
        if(!mInstanceMap.containsKey(channel)){
            LOG.d("create managed object for channel:"+channel);
            ManagedChannel instance=new ManagedChannel(channel);
            mInstanceMap.put(channel,instance);
        }
        return mInstanceMap.get(channel);
    }

    public Channel getChannel() throws IllegalStateException{
        synchronized (this) {
            if(mChannel==null){
                throw new IllegalStateException("channel is null");
            }
            return mChannel;
        }
    }

    public void setChannel(Channel channel) {
        synchronized (this) {
            mChannel = channel;
        }
    }

    private Channel mChannel;

    public ManagedChannel(Channel channel){
        setChannel(channel);
    }

    public <T extends Packet> void send(T packet,boolean needToWait) {
        final Channel channel = getChannel();
        if (packet == null)
            return;
        ChannelFuture future = channel.writeAndFlush(packet);
        if (!needToWait)
            return;
        try {
            future.sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void close(Packet closePacket, final Runnable onPostClose) {
        final Channel channel=getChannel();
        send(closePacket,true);
        channel.closeFuture().addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                future.isSuccess();//确保操作执行完成
                if(onPostClose!=null)
                    onPostClose.run();
            }
        });
        channel.close();
    }
}
